/**
 * edurender
 * SoftwareRenderer.h
 * (c) 2009 J. Brad Byrd
 */

#ifndef ER_SOFTWARERENDERER_H
#define ER_SOFTWARERENDERER_H

#include "Types.h"

#include <vector>

#include "DXUT.h"

namespace er
{
	class RenderState;

	enum Primitive
	{
		PRIMITIVE_POINTS,
		PRIMITIVE_LINES,
		PRIMITIVE_TRIANGLES,
	};

	class SoftwareRenderer
	{
	public:
		static SoftwareRenderer *Create(UInt32 width, UInt32 height);
		static void Destroy(SoftwareRenderer *renderer);

	public:
		void Resize(UInt32 width, UInt32 height);
		void GetSize(UInt32 *width, UInt32 *height) const;
		const Color *GetColorBufferPointer() const { return &m_colorBuffer[0]; }
		
	public:
		void SetColorMask(Color mask);
		void ClearColorBuffer(Color color);
		void ClearDepthBuffer(float value);

	public:
		void SetPositionPointer(UInt32 size, UInt32 byteStride, const float *positions);
		void SetNormalPointer(UInt32 byteStride, const float *normals);
		void SetTexCoordPointer(UInt32 slot, UInt32 size, UInt32 byteStride, const float *texCoords);
		void Draw(Primitive primitive, UInt32 vertexCount, UInt32 vertexOffset, const RenderState &renderState);
		//void DrawIndexed(Primitive primitive, UInt32 indexCount, const UInt16 *indices, const RenderState &renderState);
		void DrawIndexed(Primitive primitive, UInt16 minIndex, UInt16 maxIndex,
			UInt16 indexCount, const UInt16 *indices, const RenderState &renderState);

	private:
		SoftwareRenderer(UInt32 width, UInt32 height);
		~SoftwareRenderer();
		bool Initialize();
	
	private:
		void TransformVertices(UInt32 count, UInt32 offset, const D3DXMATRIX &matrix);
		void DrawPoints(UInt32 count);
		void DrawTriangle(UInt16 indexA, UInt16 indexB, UInt16 indexC);
	
	private:
		UInt32 m_width;
		UInt32 m_height;
		float m_widthf;
		float m_heightf;
		Color m_colorMask;
		std::vector<Color> m_colorBuffer;
		std::vector<float> m_depthBuffer;
	
	private:
		const float *m_positions;
		UInt32 m_positionSize;
		UInt32 m_positionStride;
		
		const float *m_normals;
		const float *m_texCoords;
	
		std::vector<UInt8> m_outputVerts;
	
	private:
		SoftwareRenderer(const SoftwareRenderer &);
		SoftwareRenderer &operator=(const SoftwareRenderer &);
	};
}

#endif // ER_SOFTWARERENDERER_H
